package com.wolfcode.goods.service.impl;

import java.util.List;

import com.wolfcode.common.utils.DateUtils;
import com.wolfcode.common.utils.SecurityUtils;
import com.wolfcode.goods.domain.GoodsStore;
import com.wolfcode.goods.domain.StockBillItem;
import com.wolfcode.goods.domain.info.StockBillInfo;
import com.wolfcode.goods.domain.vo.StockBillVo;
import com.wolfcode.goods.enums.BusBillStatusEnum;
import com.wolfcode.goods.enums.BusStockStatusEnum;
import com.wolfcode.goods.mapper.GoodsStoreMapper;
import com.wolfcode.goods.mapper.StockBillItemMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wolfcode.goods.mapper.StockBillMapper;
import com.wolfcode.goods.domain.StockBill;
import com.wolfcode.goods.service.IStockBillService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * 出入库单据Service业务层处理
 *
 * @author wolfcode
 * @date 2022-12-10
 */
@Service
public class StockBillServiceImpl implements IStockBillService {
    @Autowired
    private StockBillMapper stockBillMapper;

    @Autowired
    private StockBillItemMapper stockBillItemMapper;

    @Autowired
    private GoodsStoreMapper goodsStoreMapper;

    /**
     * 查询出入库单据
     *
     * @param id 出入库单据主键
     * @return 出入库单据
     */
    @Override
    public StockBill selectStockBillById(Long id) {
        return stockBillMapper.selectStockBillById(id);
    }

    /**
     * 查询出入库单据列表
     *
     * @param stockBill 出入库单据
     * @return 出入库单据
     */
    @Override
    public List<StockBillInfo> selectStockBillList(StockBill stockBill) {
        return stockBillMapper.selectStockBillList(stockBill);
    }

    /**
     * 新增出入库单据
     *
     * @param stockBillVo 出入库单据
     * @return 结果
     */
    @Override
    @Transactional
    public int insertStockBill(StockBillVo stockBillVo) {
        // 数据校验
        Assert.notNull(stockBillVo,"非法参数");
        // 仓库id不能为空
        Assert.notNull(stockBillVo.getStoreId(),"请选择仓库");
        // 出入库时间不能为空
        Assert.notNull(stockBillVo.getBusiDate(),"请选择出入库时间");
        StockBill stockBill = new StockBill();
        BeanUtils.copyProperties(stockBillVo, stockBill);
        stockBill.setStatus(BusBillStatusEnum.NORMAL.ordinal());
        stockBill.setOperatorId(SecurityUtils.getUserId());
        stockBill.setOperateDate(DateUtils.getNowDate());

        Integer type = stockBill.getType();// 获取出入库类型
        Long storeId = stockBill.getStoreId(); // 仓库id

        List<StockBillItem> stockBillItems = stockBillVo.getStockBillItems();
        stockBillMapper.insertStockBill(stockBill); // 插入
        stockBillItems.forEach(stockBillItem -> {
            // 这里可以拿到每一项明细
            stockBillItem.setBillId(stockBill.getId().toString()); // 设置id
            stockBillItem.setState(BusBillStatusEnum.NORMAL.ordinal());
            stockBillItemMapper.insertStockBillItem(stockBillItem);

            Long goodsId = stockBillItem.getGoodsId(); // 物品id
            Long amounts = stockBillItem.getAmounts() == null ? 0 : stockBillItem.getAmounts();// 操作的数量

            // 根据入库状态[type]来进行维系库存表(仓库id[storeId] 物品id[goodsId] 操作的数量[amounts])
            GoodsStore goodsStore = goodsStoreMapper.selectGoodsStoreByGoodsIdAndStoreId(goodsId, storeId);
            if(goodsStore == null) {
                GoodsStore store = new GoodsStore();
                store.setGoodsId(goodsId);
                store.setStoreId(storeId);
                store.setAmounts(amounts);
                goodsStoreMapper.insertGoodsStore(store);
                return;
            }
            Long count = type == BusStockStatusEnum.INPUT.ordinal() ? goodsStore.getAmounts() + amounts : goodsStore.getAmounts() - amounts;
            goodsStoreMapper.updatetGoodsStoreByGoodsIdAndStoreId(goodsId, storeId, count);

        });

        return 1;
    }

    /**
     * 修改出入库单据
     *
     * @param stockBill 出入库单据
     * @return 结果
     */
    @Override
    public int updateStockBill(StockBill stockBill) {
        return stockBillMapper.updateStockBill(stockBill);
    }

    /**
     * 批量删除出入库单据
     *
     * @param ids 需要删除的出入库单据主键
     * @return 结果
     */
    @Override
    public int deleteStockBillByIds(Long[] ids) {
        return stockBillMapper.deleteStockBillByIds(ids);
    }

    /**
     * 删除出入库单据信息
     *
     * @param id 出入库单据主键
     * @return 结果
     */
    @Override
    public int deleteStockBillById(Long id) {
        return stockBillMapper.deleteStockBillById(id);
    }

    /**
     * 获取bill详情
     */
    @Override
    public StockBillVo getStockBillInfo(Long id) {
        StockBillVo stockBillVo = new StockBillVo();
        StockBill stockBill = stockBillMapper.selectStockBillById(id);
        stockBillVo.setType(stockBill.getType());
        stockBillVo.setBusiDate(stockBill.getBusiDate());
        stockBillVo.setRemark(stockBill.getRemark());
        stockBillVo.setStockBillItems(stockBillItemMapper.selectBillItemBuyBillId(id));
        return stockBillVo;
    }

    @Override
    public int cancelBill(Long id) {
        // 取消对应的bill
        StockBill stockBill = stockBillMapper.selectStockBillById(id);
        stockBill.setStatus(BusBillStatusEnum.CANCEL.ordinal());
        // 因为是取消所以需要判断之前, 和入库出库的逻辑相反

        Integer type = stockBill.getType();// 获取出入库类型
        Long storeId = stockBill.getStoreId(); // 仓库id

        // 以及billItem
        List<StockBillItem> stockBillItems = stockBillItemMapper.selectBillItemBuyBillId(stockBill.getId());
        stockBillItems.forEach(stockBillItem -> {
            stockBillItem.setState(BusBillStatusEnum.CANCEL.ordinal());
            stockBillItemMapper.updateStockBillItem(stockBillItem);

            Long goodsId = stockBillItem.getGoodsId(); // 物品id
            Long amounts = stockBillItem.getAmounts();// 操作的数量


            // 根据入库状态[type]来进行维系库存表(仓库id[storeId] 物品id[goodsId] 操作的数量[amounts])
            GoodsStore goodsStore = goodsStoreMapper.selectGoodsStoreByGoodsIdAndStoreId(goodsId, storeId);
            Long count = type == BusStockStatusEnum.OUTPUT.ordinal() ? goodsStore.getAmounts() + amounts : goodsStore.getAmounts() - amounts;
            goodsStoreMapper.updatetGoodsStoreByGoodsIdAndStoreId(goodsId, storeId, count);
        });
        return stockBillMapper.updateStockBill(stockBill);
    }
}
